// Package service 提供业务逻辑处理服务
// 包含图片合规性检查的核心业务逻辑，整合豆包API调用和规则匹配
package service

import (
	"context"
	"crypto/md5"
	"fmt"
	"strings"
	"sync"
	"time"

	"encoding/json"
	"ubbc/internal/config"
	"ubbc/internal/interfaces"
	"ubbc/internal/model"
	"ubbc/pkg/logger"
)

// CacheEntry 缓存条目结构体
// 用于存储图片检查结果的缓存信息
type CacheEntry struct {
	Result    *model.CheckImageResponse // 检查结果
	Timestamp time.Time                 // 缓存时间
}

// CheckService 图片检查服务结构体
// 提供图片合规性检查的核心业务逻辑
type CheckService struct {
	config      *config.Config                       // 应用配置
	rules       config.Rules                         // 检查规则
	modelClient interfaces.ImageModelClientInterface // AI模型客户端接口
	logger      *logger.Logger                       // 日志记录器
	cache       map[string]*CacheEntry               // 内存缓存
	cacheMutex  sync.RWMutex                         // 缓存读写锁
	semaphore   chan struct{}                        // 并发控制信号量
}

// NewCheckService 创建新的检查服务实例
// 初始化服务依赖和并发控制机制
func NewCheckService(cfg *config.Config, rules config.Rules, modelClient interfaces.ImageModelClientInterface, log *logger.Logger) *CheckService {
	service := &CheckService{
		config:      cfg,
		rules:       rules,
		modelClient: modelClient,
		logger:      log,
		cache:       make(map[string]*CacheEntry),
		semaphore:   make(chan struct{}, cfg.Concurrency.MaxWorkers),
	}

	// 启动缓存清理协程
	if cfg.Cache.Enabled {
		go service.cacheCleanup()
	}

	return service
}

// CheckImage 检查图片合规性
// 这是服务的主要入口点，协调缓存查询、API调用和规则匹配
func (s *CheckService) CheckImage(ctx context.Context, req *model.CheckImageRequest, requestID string) (*model.CheckImageResponse, error) {
	reqLogger := s.logger.WithRequestID(requestID)

	reqLogger.Info("Starting image compliance check", map[string]interface{}{
		"image_url": req.ImageURL,
		"user_id":   req.UserID,
	})

	// 获取并发控制许可
	select {
	case s.semaphore <- struct{}{}:
		defer func() { <-s.semaphore }() // 确保释放许可
	case <-ctx.Done():
		return nil, ctx.Err()
	}

	// 检查缓存
	if s.config.Cache.Enabled {
		if cachedResult := s.getCachedResult(req.ImageURL, requestID); cachedResult != nil {
			reqLogger.Info("Returning cached result", map[string]interface{}{
				"image_url": req.ImageURL,
				"compliant": cachedResult.Compliant,
			})
			// 更新请求ID和时间戳
			cachedResult.RequestID = requestID
			cachedResult.Timestamp = time.Now()
			return cachedResult, nil
		}
	}

	// 调用AI模型API分析图片
	startTime := time.Now()
	analysisResult, err := s.modelClient.AnalyzeImage(ctx, req.ImageURL, requestID)
	if err != nil {
		reqLogger.Error("Failed to analyze image with AI model API", map[string]interface{}{
			"image_url": req.ImageURL,
			"error":     err.Error(),
			"duration":  time.Since(startTime).String(),
		})
		return nil, fmt.Errorf("failed to analyze image: %w", err)
	}

	// 解析Ollama返回的json结构
	var parsed struct {
		Violated      bool        `json:"violated"`
		ViolatedRules []string    `json:"violated_rules"`
		Details       interface{} `json:"details"`
		Description   string      `json:"description"`
	}
	if err := json.Unmarshal([]byte(analysisResult), &parsed); err == nil && parsed.Description != "" {
		response := &model.CheckImageResponse{
			Compliant:   !parsed.Violated,
			Description: parsed.Description,
			DetailedResult: map[string]interface{}{
				"violated_rules": parsed.ViolatedRules,
				"details":        parsed.Details,
			},
			OriginalImageURL: req.ImageURL,
			RequestID:        requestID,
			Timestamp:        time.Now(),
		}
		if s.config.Cache.Enabled {
			s.setCachedResult(req.ImageURL, response, requestID)
		}
		reqLogger.Info("Image compliance check completed", map[string]interface{}{
			"image_url":      req.ImageURL,
			"compliant":      response.Compliant,
			"description":    response.Description,
			"total_duration": time.Since(startTime).String(),
		})
		return response, nil
	}

	// 兼容老格式或解析失败，走原有规则
	checkResult := s.checkCompliance(analysisResult, requestID)
	response := &model.CheckImageResponse{
		Compliant:      checkResult.Compliant,
		Description:    checkResult.Description,
		DetailedResult: checkResult.DetailedResult,
		RequestID:      requestID,
		Timestamp:      time.Now(),
	}
	if s.config.Cache.Enabled {
		s.setCachedResult(req.ImageURL, response, requestID)
	}
	reqLogger.Info("Image compliance check completed", map[string]interface{}{
		"image_url":      req.ImageURL,
		"compliant":      response.Compliant,
		"description":    response.Description,
		"total_duration": time.Since(startTime).String(),
	})
	return response, nil
}

// ComplianceCheckResult 合规检查结果结构体
type ComplianceCheckResult struct {
	Compliant      bool                   // 是否合规
	Description    string                 // 检查说明
	DetailedResult map[string]interface{} // 详细检查结果
}

// checkCompliance 检查内容合规性
// 根据配置的规则检查豆包API返回的分析结果
func (s *CheckService) checkCompliance(analysisResult, requestID string) *ComplianceCheckResult {
	reqLogger := s.logger.WithRequestID(requestID)

	result := &ComplianceCheckResult{
		Compliant:      true,
		Description:    "图片内容合规",
		DetailedResult: make(map[string]interface{}),
	}

	var violations []string
	analysisLower := strings.ToLower(analysisResult)

	// 检查每个规则
	for _, rule := range s.rules {
		ruleResult := s.checkRule(rule, analysisLower, requestID)
		result.DetailedResult[rule.RulesName] = ruleResult

		if !ruleResult.Passed {
			result.Compliant = false
			violations = append(violations, ruleResult.ViolationReason)

			reqLogger.Warn("Rule violation detected", map[string]interface{}{
				"rule_name":        rule.RulesName,
				"violation_reason": ruleResult.ViolationReason,
				"matched_content":  ruleResult.MatchedContent,
			})
		}
	}

	// 设置最终描述
	if !result.Compliant {
		result.Description = fmt.Sprintf("图片内容违规：%s", strings.Join(violations, "；"))
	}

	reqLogger.Info("Compliance check completed", map[string]interface{}{
		"compliant":        result.Compliant,
		"violations_count": len(violations),
		"rules_checked":    len(s.rules),
	})

	return result
}

// RuleCheckResult 规则检查结果结构体
type RuleCheckResult struct {
	Passed          bool     `json:"passed"`           // 是否通过检查
	ViolationReason string   `json:"violation_reason"` // 违规原因
	MatchedContent  []string `json:"matched_content"`  // 匹配的内容
	RuleName        string   `json:"rule_name"`        // 规则名称
}

// checkRule 检查单个规则
// 根据规则条件检查分析结果是否违规
func (s *CheckService) checkRule(rule config.Rule, analysisResult, requestID string) *RuleCheckResult {
	reqLogger := s.logger.WithRequestID(requestID)

	result := &RuleCheckResult{
		Passed:         true,
		RuleName:       rule.RulesName,
		MatchedContent: make([]string, 0),
	}

	// 检查规则的每个条件
	for _, condition := range rule.Conditions {
		contentLower := strings.ToLower(condition.Content)
		if strings.Contains(analysisResult, contentLower) {
			result.MatchedContent = append(result.MatchedContent, condition.Content)

			// 如果条件值为true，表示这是违规内容
			if condition.Value {
				result.Passed = false
				result.ViolationReason = fmt.Sprintf("检测到%s相关内容", rule.RulesName)

				reqLogger.Debug("Rule condition matched", map[string]interface{}{
					"rule_name":       rule.RulesName,
					"matched_content": condition.Content,
					"is_violation":    condition.Value,
				})
			}
		}
	}

	return result
}

// getCachedResult 获取缓存的检查结果
// 检查缓存中是否存在有效的结果
func (s *CheckService) getCachedResult(imageURL, requestID string) *model.CheckImageResponse {
	s.cacheMutex.RLock()
	defer s.cacheMutex.RUnlock()

	cacheKey := s.generateCacheKey(imageURL)
	entry, exists := s.cache[cacheKey]
	if !exists {
		return nil
	}

	// 检查缓存是否过期
	if time.Since(entry.Timestamp) > s.config.Cache.TTL.ToDuration() {
		// 缓存过期，异步删除
		go func() {
			s.cacheMutex.Lock()
			delete(s.cache, cacheKey)
			s.cacheMutex.Unlock()
		}()
		return nil
	}

	s.logger.WithRequestID(requestID).Debug("Cache hit", map[string]interface{}{
		"image_url": imageURL,
		"cache_key": cacheKey,
		"cached_at": entry.Timestamp,
	})

	// 返回缓存结果的副本
	cachedResult := *entry.Result
	return &cachedResult
}

// setCachedResult 设置缓存结果
// 将检查结果存入缓存
func (s *CheckService) setCachedResult(imageURL string, result *model.CheckImageResponse, requestID string) {
	s.cacheMutex.Lock()
	defer s.cacheMutex.Unlock()

	cacheKey := s.generateCacheKey(imageURL)
	s.cache[cacheKey] = &CacheEntry{
		Result:    result,
		Timestamp: time.Now(),
	}

	s.logger.WithRequestID(requestID).Debug("Result cached", map[string]interface{}{
		"image_url": imageURL,
		"cache_key": cacheKey,
	})
}

// generateCacheKey 生成缓存键
// 使用图片URL的MD5哈希作为缓存键
func (s *CheckService) generateCacheKey(imageURL string) string {
	hash := md5.Sum([]byte(imageURL))
	return fmt.Sprintf("%x", hash)
}

// cacheCleanup 缓存清理协程
// 定期清理过期的缓存条目
func (s *CheckService) cacheCleanup() {
	ticker := time.NewTicker(5 * time.Minute) // 每5分钟清理一次
	defer ticker.Stop()

	for range ticker.C {
		s.cleanExpiredCache()
	}
}

// cleanExpiredCache 清理过期缓存
// 删除所有过期的缓存条目
func (s *CheckService) cleanExpiredCache() {
	s.cacheMutex.Lock()
	defer s.cacheMutex.Unlock()

	now := time.Now()
	expiredKeys := make([]string, 0)

	for key, entry := range s.cache {
		if now.Sub(entry.Timestamp) > s.config.Cache.TTL.ToDuration() {
			expiredKeys = append(expiredKeys, key)
		}
	}

	for _, key := range expiredKeys {
		delete(s.cache, key)
	}

	if len(expiredKeys) > 0 {
		s.logger.Info("Cleaned expired cache entries", "", map[string]interface{}{
			"expired_count": len(expiredKeys),
			"total_entries": len(s.cache),
		})
	}
}

// GetStats 获取服务统计信息
// 返回缓存和并发相关的统计数据
func (s *CheckService) GetStats() map[string]interface{} {
	s.cacheMutex.RLock()
	cacheSize := len(s.cache)
	s.cacheMutex.RUnlock()

	return map[string]interface{}{
		"cache_enabled":  s.config.Cache.Enabled,
		"cache_size":     cacheSize,
		"cache_ttl":      s.config.Cache.TTL.String(),
		"max_workers":    s.config.Concurrency.MaxWorkers,
		"active_workers": len(s.semaphore),
		"rules_count":    len(s.rules),
	}
}
